﻿using System.Data;
using System.Linq.Expressions;
using System.Reflection;
using EU.Core.Common;
using EU.Core.Common.DB;
using EU.Core.IRepository.Base;
using EU.Core.Model;
using EU.Core.Model.Models;
using EU.Core.Model.Tenants;
using EU.Core.Repository.UnitOfWorks;
using SqlSugar;

namespace EU.Core.Repository.Base;

public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
{
    private readonly IUnitOfWorkManage _unitOfWorkManage;
    private readonly SqlSugarScope _dbBase;

    private ISqlSugarClient _db
    {
        get
        {
            ISqlSugarClient db = _dbBase;

            //修改使用 model备注字段作为切换数据库条件，使用sqlsugar TenantAttribute存放数据库ConnId
            //参考 https://www.donet5.com/Home/Doc?typeId=2246
            var tenantAttr = typeof(TEntity).GetCustomAttribute<TenantAttribute>();
            if (tenantAttr != null)
            {
                //统一处理 configId 小写
                db = _dbBase.GetConnectionScope(tenantAttr.configId.ToString().ToLower());
                return db;
            }

            //多租户
            var mta = typeof(TEntity).GetCustomAttribute<MultiTenantAttribute>();
            if (mta is { TenantType: TenantTypeEnum.Db })
            {
                //获取租户信息 租户信息可以提前缓存下来 
                if (App.User is { TenantId: > 0 })
                {
                    var tenant = db.Queryable<SysTenant>().WithCache().Where(s => s.ID == App.User.TenantId).First();
                    if (tenant != null)
                    {
                        var iTenant = db.AsTenant();
                        if (!iTenant.IsAnyConnection(tenant.ConfigId))
                        {
                            iTenant.AddConnection(tenant.GetConnectionConfig());
                        }

                        return iTenant.GetConnectionScope(tenant.ConfigId);
                    }
                }
            }

            return db;
        }
    }

    public ISqlSugarClient Db => _db;

    public BaseRepository(IUnitOfWorkManage unitOfWorkManage)
    {
        _unitOfWorkManage = unitOfWorkManage;
        _dbBase = unitOfWorkManage.GetDbClient();
    }

    public async Task<TEntity> QueryById(object objId) => await _db.Queryable<TEntity>().In(objId).SingleAsync();

    /// <summary>
    /// 查询实体数据是否存在
    /// </summary>
    /// <param name="objId"></param>
    /// <returns></returns>
    public async Task<bool> AnyAsync(object objId) => await _db.Queryable<TEntity>().In(objId).AnyAsync();

    /// <summary>
    /// 查询实体数据是否存在
    /// </summary>
    /// <param name="objId"></param>
    /// <returns></returns>
    public bool Any(object objId) => _db.Queryable<TEntity>().In(objId).Any();

    /// <summary>
    /// 查询实体数据是否存在
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns></returns>
    public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> whereExpression)
    {
        return await _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).AnyAsync();
    }
    /// <summary>
    /// 根据ID查询一条数据
    /// </summary>
    /// <param name="objId">id（必须指定主键特性 [SugarColumn(IsPrimaryKey=true)]），如果是联合主键，请使用Where条件</param>
    /// <param name="blnUseCache">是否使用缓存</param>
    /// <returns>数据实体</returns>
    public async Task<TEntity> QueryById(object objId, bool blnUseCache = false) => await _db.Queryable<TEntity>().WithCacheIF(blnUseCache, 10).In(objId).SingleAsync();

    /// <summary>
    /// 根据ID查询数据
    /// </summary>
    /// <param name="lstIds">id列表（必须指定主键特性 [SugarColumn(IsPrimaryKey=true)]），如果是联合主键，请使用Where条件</param>
    /// <returns>数据实体列表</returns>
    public async Task<List<TEntity>> QueryByIDs(object[] lstIds) => await _db.Queryable<TEntity>().In(lstIds).ToListAsync();

    /// <summary>
    /// 写入实体数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <returns></returns>
    public async Task<Guid> Add(TEntity entity, Guid? id = null)
    {
        var id1 = Guid.Empty;
        if (id != null)
            if (entity is RootEntityTkey<Guid> rootEntity1)
                rootEntity1.ID = id.Value;
        var insert = _db.Insertable(entity);
        string sql = insert.ToSqlString();
        if (entity is RootEntityTkey<Guid> rootEntity)
            id1 = rootEntity.ID;
        await _db.Ado.ExecuteCommandAsync(sql);
        return id1;
    }

    /// <summary>
    /// 写入实体数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <param name="insertColumns">指定只插入列</param>
    /// <returns>返回自增量列</returns>
    public async Task<long> Add(TEntity entity, Expression<Func<TEntity, object>> insertColumns = null)
    {
        var insert = _db.Insertable(entity);
        if (insertColumns == null)
            return await insert.ExecuteReturnSnowflakeIdAsync();
        else
            return await insert.InsertColumns(insertColumns).ExecuteReturnSnowflakeIdAsync();
    }
    /// <summary>
    /// 写入实体数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <param name="insertColumns">指定只插入列</param>
    /// <returns>返回自增量列</returns>
    public async Task<Guid> Add(TEntity entity, List<string> insertColumns)
    {
        insertColumns.Add("ID");
        insertColumns.Add("CreatedBy");
        insertColumns.Add("CreatedTime");

        var id = Guid.Empty;
        var insert = _db.Insertable(entity);
        string sql = insert.InsertColumns(insertColumns.ToArray()).ToSqlString();
        if (entity is RootEntityTkey<Guid> rootEntity)
        {
            id = rootEntity.ID;
        }
        await _db.Ado.ExecuteCommandAsync(sql);
        return id;
    }

    /// <summary>
    /// 批量插入实体(速度快)
    /// </summary>
    /// <param name="listEntity">实体集合</param>
    /// <returns>影响行数</returns>
    public async Task<List<Guid>> Add(List<TEntity> listEntity)
    {
        if (listEntity is null || !listEntity.Any())
            return new List<Guid>();
        var ids = new List<Guid>();
        var insert = _db.Insertable(listEntity);
        string sql = insert.ToSqlString();
        foreach (var entity in listEntity)
        {
            if (entity is RootEntityTkey<Guid> rootEntity)
                ids.Add(rootEntity.ID);
        }
        await _db.Ado.ExecuteCommandAsync(sql);
        return ids;
    }

    /// <summary>
    /// 更新实体数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <returns></returns>
    public async Task<bool> Update(TEntity entity) => await _db.Updateable(entity).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 更新实体数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <returns></returns>
    public async Task<bool> Update(List<TEntity> entity) => await _db.Updateable(entity).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 更新实体数据
    /// </summary>
    /// <param name="entitys">实体类</param>
    /// <param name="lstColumns">只更新某列</param>
    /// <param name="lstIgnoreColumns">不更新某列</param>
    /// <param name="where">where条件</param>
    /// <returns></returns>
    public async Task<bool> Update(List<TEntity> entitys, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string where = null)
    {
        var up = _db.Updateable(entitys);
        if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
            up = up.IgnoreColumns(lstIgnoreColumns.ToArray());

        if (lstColumns != null && lstColumns.Count > 0)
        {
            lstColumns.Add("UpdateBy");
            lstColumns.Add("UpdateTime");
            lstColumns.Add("ModificationNum");
            up = up.UpdateColumns(lstColumns.ToArray());
        }

        if (!string.IsNullOrEmpty(where))
            up = up.Where(where);

        return await up.ExecuteCommandHasChangeAsync();
    }

    public async Task<bool> Update(TEntity entity, string where) => await _db.Updateable(entity).Where(where).ExecuteCommandHasChangeAsync();

    public async Task<bool> Update(string sql, SugarParameter[] parameters = null) => await _db.Ado.ExecuteCommandAsync(sql, parameters) > 0;

    public async Task<bool> Update(object operateAnonymousObjects) => await _db.Updateable<TEntity>(operateAnonymousObjects).ExecuteCommandAsync() > 0;

    /// <summary>
    /// 更新实体数据
    /// </summary>
    /// <param name="entitys">实体类</param>
    /// <param name="lstColumns">只更新某列</param>
    /// <param name="lstIgnoreColumns">不更新某列</param>
    /// <param name="where">where条件</param>
    /// <returns></returns>
    public async Task<bool> Update(TEntity entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string where = null)=> await Update([entity], lstColumns, lstIgnoreColumns, where);

    /// <summary>
    /// 根据实体删除一条数据
    /// </summary>
    /// <param name="entity">实体类</param>
    /// <returns></returns>
    public async Task<bool> Delete(TEntity entity) => await _db.Deleteable(entity).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 根据表达式，删除实体
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns></returns>
    public async Task<bool> Delete(Expression<Func<TEntity, bool>> whereExpression) => await _db.Deleteable<TEntity>().Where(whereExpression).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 删除指定ID的数据
    /// </summary>
    /// <param name="id">主键ID</param>
    /// <returns></returns>
    public async Task<bool> DeleteById(object id) => await _db.Deleteable<TEntity>().In(id).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 删除指定ID集合的数据(批量删除)
    /// </summary>
    /// <param name="ids">主键ID集合</param>
    /// <returns></returns>
    public async Task<bool> DeleteByIds(object[] ids) => await _db.Deleteable<TEntity>().In(ids).ExecuteCommandHasChangeAsync();

    /// <summary>
    /// 查询所有数据
    /// </summary>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query() => await _db.Queryable<TEntity>().ToListAsync();

    /// <summary>
    /// 查询数据列表
    /// </summary>
    /// <param name="where">条件</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(string where) => await _db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(where), where).ToListAsync();

    /// <summary>
    /// 查询数据列表
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression) => await _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).ToListAsync();

    /// <summary>
    /// 按照特定列查询数据列表
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="expression"></param>
    /// <returns></returns>
    public async Task<List<TResult>> Query<TResult>(Expression<Func<TEntity, TResult>> expression) => await _db.Queryable<TEntity>().Select(expression).ToListAsync();

    /// <summary>
    /// 按照特定列查询单个数据
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="expression"></param>
    /// <returns></returns>
    public async Task<TEntity> QuerySingle(Expression<Func<TEntity, bool>> expression) => await _db.Queryable<TEntity>().Where(expression).FirstAsync();

    /// <summary>
    /// 按照特定列查询数据列表带条件排序
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <param name="whereExpression">过滤条件</param>
    /// <param name="expression">查询实体条件</param>
    /// <param name="orderByFields">排序条件</param>
    /// <returns></returns>
    public async Task<List<TResult>> Query<TResult>(Expression<Func<TEntity, TResult>> expression, Expression<Func<TEntity, bool>> whereExpression, string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Select(expression).ToListAsync();
    }

    /// <summary>
    /// 查询一个列表
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string orderByFields)
    {
        return await _db.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).OrderByIF(orderByFields != null, orderByFields).ToListAsync();
    }

    /// <summary>
    /// 查询一个列表
    /// </summary>
    /// <param name="whereExpression"></param>
    /// <param name="orderByExpression"></param>
    /// <param name="isAsc"></param>
    /// <returns></returns>
    public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true)
    {
        //return await Task.Run(() => _db.Queryable<TEntity>().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToList());
        return await _db.Queryable<TEntity>().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToListAsync();
    }

    /// <summary>
    /// 查询一个列表
    /// </summary>
    /// <param name="where">条件</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(string where, string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).ToListAsync();
    }


    /// <summary>
    /// 查询前N条数据
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="top">前N条</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(
        Expression<Func<TEntity, bool>> whereExpression,
        int top,
        string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(whereExpression != null, whereExpression).Take(top).ToListAsync();
    }

    /// <summary>
    /// 查询前N条数据
    /// </summary>
    /// <param name="where">条件</param>
    /// <param name="top">前N条</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(string where, int top, string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields).WhereIF(!string.IsNullOrEmpty(where), where).Take(top).ToListAsync();
    }

    /// <summary>
    /// 根据sql语句查询
    /// </summary>
    /// <param name="sql">完整的sql语句</param>
    /// <param name="parameters">参数</param>
    /// <returns>泛型集合</returns>
    public async Task<List<TEntity>> QuerySql(string sql, SugarParameter[] parameters = null) => await _db.Ado.SqlQueryAsync<TEntity>(sql, parameters);

    /// <summary>
    /// 根据sql语句查询
    /// </summary>
    /// <param name="sql">完整的sql语句</param>
    /// <param name="parameters">参数</param>
    /// <returns>DataTable</returns>
    public async Task<DataTable> QueryTable(string sql, SugarParameter[] parameters = null) => await _db.Ado.GetDataTableAsync(sql, parameters);

    /// <summary>
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="pageIndex">页码（下标0）</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(
        Expression<Func<TEntity, bool>> whereExpression,
        int pageIndex,
        int pageSize,
        string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(whereExpression != null, whereExpression).ToPageListAsync(pageIndex, pageSize);
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="where">条件</param>
    /// <param name="pageIndex">页码（下标0）</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns>数据列表</returns>
    public async Task<List<TEntity>> Query(
        string where,
        int pageIndex,
        int pageSize,
        string orderByFields)
    {
        return await _db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(!string.IsNullOrEmpty(where), where).ToPageListAsync(pageIndex, pageSize);
    }


    /// <summary>
    /// 分页查询[使用版本，其他分页未测试]
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="pageIndex">页码（下标0）</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns></returns>
    public async Task<PageModel<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null)
    {
        RefAsync<int> totalCount = 0;
        var list = await _db.Queryable<TEntity>()
            .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(whereExpression != null, whereExpression)
            .ToPageListAsync(pageIndex, pageSize, totalCount);

        return new PageModel<TEntity>(pageIndex, totalCount, pageSize, list);
    }
    /// <summary>
    /// 分页查询[使用版本，其他分页未测试]
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="pageIndex">页码（下标0）</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns></returns>
    public async Task<ServicePageResult<TEntity>> QueryFilterPage([FromFilter] QueryFilter filter)
    {
        RefAsync<int> totalCount = 0;
        var query = _db.Queryable<TEntity>();
        if (!filter.Conditions.IsNullOrEmpty())
            query = query.Where(filter.Conditions);

        var list = await query
            .OrderByIF(!string.IsNullOrEmpty(filter.Sorting), filter.Sorting)
            .ToPageListAsync(filter.PageIndex, filter.PageSize, totalCount);

        return new ServicePageResult<TEntity>(filter.PageIndex, totalCount, filter.PageSize, list);
    }


    /// <summary> 
    ///查询-多表查询
    /// </summary> 
    /// <typeparam name="T">实体1</typeparam> 
    /// <typeparam name="T2">实体2</typeparam> 
    /// <typeparam name="T3">实体3</typeparam>
    /// <typeparam name="TResult">返回对象</typeparam>
    /// <param name="joinExpression">关联表达式 (join1,join2) => new object[] {JoinType.Left,join1.UserNo==join2.UserNo}</param> 
    /// <param name="selectExpression">返回表达式 (s1, s2) => new { Id =s1.UserNo, Id1 = s2.UserNo}</param>
    /// <param name="whereLambda">查询表达式 (w1, w2) =>w1.UserNo == "")</param> 
    /// <returns>值</returns>
    public async Task<List<TResult>> QueryMuch<T, T2, T3, TResult>(
        Expression<Func<T, T2, T3, object[]>> joinExpression,
        Expression<Func<T, T2, T3, TResult>> selectExpression,
        Expression<Func<T, T2, T3, bool>> whereLambda = null) where T : class, new()
    {
        if (whereLambda == null)
            return await _db.Queryable(joinExpression).Select(selectExpression).ToListAsync();
        return await _db.Queryable(joinExpression).Where(whereLambda).Select(selectExpression).ToListAsync();
    }

    /// <summary>
    /// 两表联合查询-分页
    /// </summary>
    /// <typeparam name="T">实体1</typeparam>
    /// <typeparam name="T2">实体1</typeparam>
    /// <typeparam name="TResult">返回对象</typeparam>
    /// <param name="joinExpression">关联表达式</param>
    /// <param name="selectExpression">返回表达式</param>
    /// <param name="whereExpression">查询表达式</param>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段</param>
    /// <returns></returns>
    public async Task<PageModel<TResult>> QueryTabsPage<T, T2, TResult>(
        Expression<Func<T, T2, object[]>> joinExpression,
        Expression<Func<T, T2, TResult>> selectExpression,
        Expression<Func<TResult, bool>> whereExpression,
        int pageIndex = 1,
        int pageSize = 20,
        string orderByFields = null)
    {
        RefAsync<int> totalCount = 0;
        var list = await _db.Queryable<T, T2>(joinExpression)
            .Select(selectExpression)
            .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(whereExpression != null, whereExpression)
            .ToPageListAsync(pageIndex, pageSize, totalCount);
        return new PageModel<TResult>(pageIndex, totalCount, pageSize, list);
    }

    /// <summary>
    /// 两表联合查询-分页-分组
    /// </summary>
    /// <typeparam name="T">实体1</typeparam>
    /// <typeparam name="T2">实体1</typeparam>
    /// <typeparam name="TResult">返回对象</typeparam>
    /// <param name="joinExpression">关联表达式</param>
    /// <param name="selectExpression">返回表达式</param>
    /// <param name="whereExpression">查询表达式</param>
    /// <param name="groupExpression">group表达式</param>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段</param>
    /// <returns></returns>
    public async Task<PageModel<TResult>> QueryTabsPage<T, T2, TResult>(
        Expression<Func<T, T2, object[]>> joinExpression,
        Expression<Func<T, T2, TResult>> selectExpression,
        Expression<Func<TResult, bool>> whereExpression,
        Expression<Func<T, object>> groupExpression,
        int pageIndex = 1,
        int pageSize = 20,
        string orderByFields = null)
    {
        RefAsync<int> totalCount = 0;
        var list = await _db.Queryable<T, T2>(joinExpression).GroupBy(groupExpression)
            .Select(selectExpression)
            .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(whereExpression != null, whereExpression)
            .ToPageListAsync(pageIndex, pageSize, totalCount);
        return new PageModel<TResult>(pageIndex, totalCount, pageSize, list);
    }

    //var exp = Expressionable.Create<ProjectToUser>()
    //        .And(s => s.tdIsDelete != true)
    //        .And(p => p.IsDeleted != true)
    //        .And(p => p.pmId != null)
    //        .AndIF(!string.IsNullOrEmpty(model.paramCode1), (s) => s.uID == model.paramCode1.ObjToInt())
    //                .AndIF(!string.IsNullOrEmpty(model.searchText), (s) => (s.groupName != null && s.groupName.Contains(model.searchText))
    //                        || (s.jobName != null && s.jobName.Contains(model.searchText))
    //                        || (s.uRealName != null && s.uRealName.Contains(model.searchText)))
    //                .ToExpression();//拼接表达式
    //var data = await _projectMemberServices.QueryTabsPage<sysUserInfo, ProjectMember, ProjectToUser>(
    //    (s, p) => new object[] { JoinType.Left, s.uID == p.uId },
    //    (s, p) => new ProjectToUser
    //    {
    //        uID = s.uID,
    //        uRealName = s.uRealName,
    //        groupName = s.groupName,
    //        jobName = s.jobName
    //    }, exp, s => new { s.uID, s.uRealName, s.groupName, s.jobName }, model.currentPage, model.pageSize, model.orderField + " " + model.orderType);

    #region Split分表基础接口 （基础CRUD）

    /// <summary>
    /// 分页查询[使用版本，其他分页未测试]
    /// </summary>
    /// <param name="whereExpression">条件表达式</param>
    /// <param name="pageIndex">页码（下标0）</param>
    /// <param name="pageSize">页大小</param>
    /// <param name="orderByFields">排序字段，如name asc,age desc</param>
    /// <returns></returns>
    public async Task<PageModel<TEntity>> QueryPageSplit(Expression<Func<TEntity, bool>> whereExpression, DateTime beginTime, DateTime endTime, int pageIndex = 1, int pageSize = 20, string orderByFields = null)
    {
        RefAsync<int> totalCount = 0;
        var list = await _db.Queryable<TEntity>().SplitTable(beginTime, endTime)
            .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
            .WhereIF(whereExpression != null, whereExpression)
            .ToPageListAsync(pageIndex, pageSize, totalCount);
        return new PageModel<TEntity>(pageIndex, totalCount, pageSize, list);
    }

    /// <summary>
    /// 写入实体数据
    /// </summary>
    /// <param name="entity">数据实体</param>
    /// <returns></returns>
    public async Task<List<long>> AddSplit(TEntity entity)
    {
        var insert = _db.Insertable(entity).SplitTable();
        //插入并返回雪花ID并且自动赋值ID　
        return await insert.ExecuteReturnSnowflakeIdListAsync();
    }

    /// <summary>
    /// 更新实体数据
    /// </summary>
    /// <param name="entity">数据实体</param>
    /// <returns></returns>
    public async Task<bool> UpdateSplit(TEntity entity, DateTime dateTime)
    {
        //直接根据实体集合更新 （全自动 找表更新）
        //return await _db.Updateable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少

        //精准找单个表
        var tableName = _db.SplitHelper<TEntity>().GetTableName(dateTime); //根据时间获取表名
        return await _db.Updateable(entity).AS(tableName).ExecuteCommandHasChangeAsync();
    }

    /// <summary>
    /// 删除数据
    /// </summary>
    /// <param name="entity"></param>
    /// <param name="dateTime"></param>
    /// <returns></returns>
    public async Task<bool> DeleteSplit(TEntity entity, DateTime dateTime)
    {
        ////直接根据实体集合删除 （全自动 找表插入）,返回受影响数
        //return await _db.Deleteable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少

        //精准找单个表
        var tableName = _db.SplitHelper<TEntity>().GetTableName(dateTime); //根据时间获取表名
        return await _db.Deleteable<TEntity>().AS(tableName).Where(entity).ExecuteCommandHasChangeAsync();
    }

    /// <summary>
    /// 根据ID查找数据
    /// </summary>
    /// <param name="objId"></param>
    /// <returns></returns>
    public async Task<TEntity> QueryByIdSplit(object objId) => await _db.Queryable<TEntity>().In(objId).SplitTable(tabs => tabs).SingleAsync();

    /// <summary>
    /// 数据过滤用的查询表达式构建
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <returns></returns>
    protected Expression<Func<TEntity, bool>> CreateFilterExpression<T>()
        where T : class
    {
        Expression<Func<TEntity, bool>> expression = null;

        //if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
        //{
        //    Expression<Func<TEntity, bool>> softDeleteFilter = e => !((ISoftDelete)e).IsDeleted;
        //    expression = expression == null ? softDeleteFilter : CombineExpressions(expression, softDeleteFilter);
        //}

        if (typeof(IMayHaveTenant).IsAssignableFrom(typeof(TEntity)))// && IsMayHaveTenantFilterEnabled)
        {
            Expression<Func<TEntity, bool>> mayHaveTenantFilter = e => ((IMayHaveTenant)e).IsEnable == 1;
            expression = expression == null
                ? mayHaveTenantFilter
                : CombineExpressions(expression, mayHaveTenantFilter);
        }

        return expression;
    }
    protected Expression<Func<T, bool>> CombineExpressions<T>(Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2) => Common.Helper.ExpressionCombiner.Combine(expression1, expression2);

    #endregion
}

public interface IMayHaveTenant
{
    int IsEnable { get; set; }
}